import type { PlatformTypeValue } from '../../../types/interfaces'
import { BaseModule } from '../../../lib/abstract'
import {
  getPlatformValue,
  HOSTNAME,
  logger,
  SUPPORTED_PLATFORMS,
} from '../../../types/constants'
import { ConfigManager } from '../../config_manager'

interface PlatformRule {
  selector?: string
  precondition?: () => boolean
  condition: () => boolean
  action: 'remove' | 'hide' | (($elements: JQuery) => void)
  pollOptions?: {
    interval?: number
    maxAttempts?: number
    immediate?: boolean
  }
}
interface Config {
  enabled?: boolean
  rules?: {
    [K in PlatformTypeValue]?: PlatformRule[]
  }
}

type Rules = {
  [K in PlatformTypeValue]?: PlatformRule[]
}

/**
 * 付费墙处理器模块
 * 【CSDN】
 * 1）订阅专栏：https://blog.csdn.net/Qmtdearu/article/details/149584259（不支持解锁）
 * 2）VIP免费：https://blog.csdn.net/Syyynb/article/details/138673154 （只能解锁一部分内容，不能解锁全部）
 * 3）关注阅读：xxx（解锁全部内容）
 */
export class PayWallHandler extends BaseModule {
  readonly id: string = 'paywall_handler'
  readonly name: string = 'PayWallHandler'
  readonly isInitialized: boolean = false
  readonly supportedPlatforms: string[] = ConfigManager.getInstance().moduleSupportedPlatforms(this.name)
  private static instance: PayWallHandler

  config: Config = {
    enabled: true,
  }

  protected rules: Rules = {
    [SUPPORTED_PLATFORMS.CSDN]: [
      {
        precondition: () => {
          const $el = $('.hide-article-box').not(':has(.bt-subscribe-article)')
          return $el.length > 0 && $el.is(':visible')
        },
        condition: () => {
          const $el = $('.hide-article-box')
          return $el.length > 0 && $el.is(':visible')
        },
        action: () => {
          $('.hide-article-box').remove()
          $('#article_content').css({
            height: '',
            overflow: '',
          })
        },
      },
    ],
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): PayWallHandler {
    if (!PayWallHandler.instance) {
      PayWallHandler.instance = new PayWallHandler()
    }
    return PayWallHandler.instance
  }

  /**
   * 销毁模块
   */
  destroy(): void {
    super.destroy()
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.applyRules()
  }

  onToggleCallback(_id: string, checked: boolean): void {
    super.onToggleCallback(_id, checked)
  }

  /**
   * 处理单个规则
   */
  private handleRule(rule: PlatformRule) {
    const { selector, action, precondition, condition, pollOptions } = rule
    const $elements = selector ? $(selector) : $([])

    const executeAction = () => {
      // 执行条件检查
      if (condition && !condition()) {
        return false
      }

      // 执行动作
      if (typeof action === 'function') {
        action($elements)
      }
      else {
        switch (action) {
          case 'remove':
            $elements.remove()
            break
          case 'hide':
            $elements.hide()
            break
        }
      }
      return true
    }

    if (!precondition || !precondition())
      return

    if (pollOptions) {
      this.pollingHandler.api.awaitCondition(
        condition,
        executeAction,
      )
    }
    else {
      executeAction()
    }
  }

  /**
   * 应用规则
   */
  private applyRules() {
    const platformValue = getPlatformValue(HOSTNAME)
    if (!platformValue)
      return

    const rules = this.rules?.[platformValue] ?? []
    rules.forEach((rule) => {
      this.handleRule(rule)
    })
    logger.info(`[${this.name}] Rules applied`)
  }

  /**
   * 应用新配置并更新模块
   */
  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)
    // 重新应用规则
    this.applyRules()
    logger.info(`[${this.name}] Config updated and apply`, this.config)
  }
}
